package cn.stylefeng.guns.modular.time.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cn.stylefeng.guns.modular.time.entity.Transaction;
import cn.stylefeng.guns.modular.time.mapper.TransactionMapper;
import cn.stylefeng.guns.modular.time.model.request.TransactionRequest;
import cn.stylefeng.guns.modular.time.service.TransactionService;
import cn.stylefeng.roses.kernel.auth.api.context.LoginContext;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class TransactionServiceImpl extends ServiceImpl<TransactionMapper, Transaction> implements TransactionService {

    @Override
    public PageResult<Transaction> findPage(TransactionRequest request) {
        LambdaQueryWrapper<Transaction> qw = new LambdaQueryWrapper<>();
        qw.eq(Transaction::getDelFlag, "N")
          .eq(Transaction::getUserId, LoginContext.me().getLoginUser().getUserId());
        if (request.getStartDate() != null) {
            qw.ge(Transaction::getTransactionDate, request.getStartDate());
        }
        if (request.getEndDate() != null) {
            qw.le(Transaction::getTransactionDate, request.getEndDate());
        }
        if (request.getCategory() != null && !request.getCategory().isEmpty()) {
            qw.eq(Transaction::getCategory, request.getCategory());
        }
        qw.orderByDesc(Transaction::getTransactionDate).orderByDesc(Transaction::getCreateTime);
        Page<Transaction> page = this.page(new Page<>(request.getPageNo(), request.getPageSize()), qw);
        return PageResultFactory.createPageResult(page);
    }

    @Override
    public void add(TransactionRequest request) {
        Transaction t = new Transaction();
        t.setTransactionId(null);
        t.setUserId(LoginContext.me().getLoginUser().getUserId());
        t.setAmount(request.getAmount());
        t.setType(request.getType());
        t.setCategory(request.getCategory());
        t.setTransactionDate(request.getTransactionDate());
        t.setNote(request.getNote());
        t.setDelFlag("N");
        t.setCreateTime(new Date());
        this.save(t);
    }

    @Override
    public void edit(TransactionRequest request) {
        Transaction t = this.getById(request.getTransactionId());
        if (t != null) {
            t.setAmount(request.getAmount());
            t.setType(request.getType());
            t.setCategory(request.getCategory());
            t.setTransactionDate(request.getTransactionDate());
            t.setNote(request.getNote());
            t.setUpdateTime(new Date());
            this.updateById(t);
        }
    }

    @Override
    public void delete(TransactionRequest request) {
        this.removeById(request.getTransactionId());
    }

    @Override
    public List<Map<String, Object>> statsByCategory(TransactionRequest request) {
        LambdaQueryWrapper<Transaction> qw = new LambdaQueryWrapper<>();
        qw.eq(Transaction::getDelFlag, "N")
          .eq(Transaction::getUserId, LoginContext.me().getLoginUser().getUserId());
        if (request.getStartDate() != null) {
            qw.ge(Transaction::getTransactionDate, request.getStartDate());
        }
        if (request.getEndDate() != null) {
            qw.le(Transaction::getTransactionDate, request.getEndDate());
        }
        List<Transaction> list = this.list(qw);
        Map<String, java.math.BigDecimal> grouped = list.stream()
            .collect(Collectors.groupingBy(
                t -> Optional.ofNullable(t.getCategory()).orElse("其他"),
                Collectors.reducing(java.math.BigDecimal.ZERO, Transaction::getAmount, java.math.BigDecimal::add)
            ));
        List<Map<String, Object>> result = new ArrayList<>();
        grouped.forEach((k, v) -> {
            Map<String, Object> m = new HashMap<>();
            m.put("category", k);
            m.put("amount", v);
            result.add(m);
        });
        result.sort((a, b) -> ((java.math.BigDecimal)b.get("amount")).compareTo((java.math.BigDecimal)a.get("amount")));
        return result;
    }
}

